﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Dynamic;
using System.Collections.Specialized;
using System.Collections.Concurrent;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace DBMan.Common.Global
{
    public class Tool
    {

        /// <summary>
        /// 将Dictionary转换成为Dynamic对象
        /// </summary>
        /// <param name="dict"></param>
        /// <returns></returns>
        private static dynamic ToDynamic0(IDictionary<string, object> dict)
        {
            dynamic result = new ExpandoObject();
            foreach (var entry in dict)
            {
                (result as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>(entry.Key, entry.Value));
            }
            return result;
        }

        /// <summary>
        /// 判断dynamic类型的数据对象是否存在某个属性
        /// </summary>
        /// <param name="data"></param>
        /// <param name="propertyname"></param>
        /// <returns></returns>
        public static bool IsPropertyExist(dynamic data, string propertyname)
        {
            if (data is ExpandoObject)
                return ((IDictionary<string, object>)data).ContainsKey(propertyname);
            return data.GetType().GetProperty(propertyname) != null;
        }

        /// <summary>
        /// 由json返回Dynamic扩展对象列表
        /// </summary>
        /// <param name="json"></param>
        /// <param name="isPropertyInitialsLower"></param>
        /// <returns></returns>
        public static List<DynamicObjectEx> ToDynamicsByJson(string json, bool isPropertyInitialsLower = true)
        {
            List<DynamicObjectEx> ltRet = new List<DynamicObjectEx>();
            try
            {
                json = (json ?? "").Trim();
                if (string.IsNullOrEmpty(json))
                {
                    return ltRet;
                }
                var jsonTag = json.Substring(0, 1);
                if (!((new string[] { "[", "{" }).Any(p => p == jsonTag)))
                {
                    return ltRet;
                }
                if (jsonTag == "{")
                {
                    json = $"[{json}]";
                }
                JArray jA = JArray.Parse(json);
                foreach (var jt in jA)
                {
                    var jo = (JObject)jt;
                    Dictionary<string, object> dic = new Dictionary<string, object>();
                    foreach (JProperty jProperty in jo.Properties())
                    {
                        string strPropertyName = jProperty.Name;
                        if (isPropertyInitialsLower)
                        {
                            var str = strPropertyName.Substring(0, 1).ToLower();
                            strPropertyName = str + strPropertyName.Substring(1, strPropertyName.Length - 1);
                        }
                        object objValue = jProperty.Value;
                        if (dic.ContainsKey(strPropertyName))
                        {
                            dic[strPropertyName] = objValue;
                        }
                        else
                        {
                            dic.Add(strPropertyName, objValue);
                        }
                    }
                    var dyRet = ToDynamic0(dic);
                    ltRet.Add(new DynamicObjectEx(dyRet));
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"Tool ToDynamicsByHttp Err:{ex.Message}");
            }
            return ltRet;
        }

        /// <summary>
        /// 获取 某文件夹下的所有文件路径 含子文件夹的文件路径
        /// </summary>
        /// <param name="folderPath"></param>
        /// <param name="ltFile"></param>
        public static void GetAllFilesInFolder(string folderPath, ref List<string> ltFile)
        {
            try
            {
                if (!Directory.Exists(folderPath))
                {
                    return;
                }
                DirectoryInfo directoryInfo = new DirectoryInfo(folderPath);
                foreach (FileInfo file in directoryInfo.GetFiles())
                {
                    //Console.WriteLine("文件名称: " + file.Name);
                    ltFile.Add(file.FullName);
                }
                foreach (DirectoryInfo subdirectory in directoryInfo.GetDirectories())
                {
                    GetAllFilesInFolder(subdirectory.FullName, ref ltFile);
                }
            }
            catch (Exception ex)
            {
                //Console.WriteLine("发生错误: " + ex.Message);
                LogWrite.TxtExport_DateNow("LogErr.txt", $"Tool GetAllFilesInFolder Err:{ex.Message}");
            }
        }

        /// <summary>
        /// 判断一个字符串是否为Json格式
        /// </summary>
        /// <param name="strInput"></param>
        /// <returns></returns>
        public static bool IsJson(string strInput)
        {
            try
            {
                try
                {
                    JToken.Parse(strInput);
                    return true;
                }
                catch (JsonReaderException)
                {
                    return false;
                }
                catch (JsonSerializationException)
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"Tool IsJson Err:{ex.Message}");
            }
            return false;
        }

        /// <summary>
        /// 格式化json字符串
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string ConvertJsonString(string str)
        {
            try
            {
                JsonSerializer serializer = new JsonSerializer();
                TextReader tr = new StringReader(str);
                JsonTextReader jtr = new JsonTextReader(tr);
                object obj = serializer.Deserialize(jtr);
                if (obj != null)
                {
                    StringWriter textWriter = new StringWriter();
                    JsonTextWriter jsonWriter = new JsonTextWriter(textWriter)
                    {
                        Formatting = Formatting.Indented,
                        Indentation = 4,
                        IndentChar = ' '
                    };
                    serializer.Serialize(jsonWriter, obj);
                    return textWriter.ToString();
                }
                else
                {
                    return str;
                }
            }
            catch { }
            return str;
        }

    }

    public class DynamicObjectEx
    {
        private dynamic DyObj = null;
        public DynamicObjectEx(dynamic dyObj)
        {
            this.DyObj = dyObj;//new ExpandoObject();
        }
        /// <summary>
        /// dynamic对像
        /// </summary>
        public dynamic Dy
        {
            get
            {
                return this.DyObj;
            }
        }
        /// <summary>
        /// 获取dynamic对像某属性值
        /// </summary>
        /// <param name="propertyname">属性名</param>
        /// <returns></returns>
        public dynamic Get(string propertyname)
        {
            dynamic dyRet = null;
            if (Tool.IsPropertyExist(this.DyObj, propertyname))
            {
                dyRet = ((IDictionary<string, object>)this.DyObj)[propertyname];
            }
            return dyRet;
        }

        public T Get<T>(string propertyname)
        {
            try
            {
                dynamic dy = this.Get(propertyname);
                if (dy == null)
                {
                    return default(T);
                }
                T t = (T)dy;
                return t;
            }
            catch { }
            return default(T);
        }

        public T Get2<T>(string propertyname)
        {
            try
            {
                dynamic dy = this.Get(propertyname);
                if (dy == null)
                {
                    return default(T);
                }
                string json = JsonConvert.SerializeObject(dy);
                var t = JsonConvert.DeserializeObject<T>(json);
                return t;
            }
            catch { }
            return default(T);
        }

        /// <summary>
        /// 获取dynamic对像某属性的DynamicObjectEx对像列表
        /// </summary>
        /// <param name="propertyname"></param>
        /// <returns></returns>
        public List<DynamicObjectEx> Get3(string propertyname)
        {
            var ltRet = new List<DynamicObjectEx>();
            try
            {
                var dy = this.Get(propertyname);
                if (dy == null)
                {
                    return ltRet;
                }
                string json = JsonConvert.SerializeObject(dy);
                ltRet = Tool.ToDynamicsByJson(json);
            }
            catch { }
            return ltRet;
        }
        /// <summary>
        ///  获取dynamic对像某属性的DynamicObjectEx对像
        /// </summary>
        /// <param name="propertyname"></param>
        /// <returns></returns>
        public DynamicObjectEx Get5(string propertyname)
        {
            var lt = this.Get3(propertyname);
            if (lt.Any())
            {
                return lt.First();
            }
            return null;
        }
    }

    public static class ToolHelper
    {
        /// <summary>
        /// 获取对像的Json字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string ToJsonByKnD(this object obj)
        {
            try
            {
                if (obj == null)
                {
                    return "";
                }
                var json = obj.ToString();
                if (Tool.IsJson(json))
                {
                    return json;
                }
                json = JsonConvert.SerializeObject(obj);
                return json;
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper ToJsonByKnD Err:{ex.Message}");
            }
            return "";
        }

        /// <summary>
        /// 获取不同操作系统平台下的转换路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string GetRuntimeDirectoryByKnD(this string path)
        {
            try
            {
                //ForLinux
                if (IsLinuxRunTime())
                    return GetLinuxDirectory(path);
                //ForWindows
                if (IsWindowRunTime())
                    return GetWindowDirectory(path);
            }
            catch //(Exception ex)
            {
                //KndSystem.Common.Logging.Logger.Error(ex.ToString());
            }
            return path;

        }

        //OSPlatform.Windows监测运行环境
        private static bool IsWindowRunTime()
        {
            return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
        }

        //OSPlatform.Linux运行环境
        private static bool IsLinuxRunTime()
        {
            return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Linux);
        }

        private static string GetLinuxDirectory(string path)
        {
            string pathTemp = Path.Combine(path);
            return pathTemp.Replace("\\", "/");
        }
        private static string GetWindowDirectory(string path)
        {
            string pathTemp = Path.Combine(path);
            return pathTemp.Replace("/", "\\");
        }

        public static string DNTryPeek(this ConcurrentQueue<string> qu)
        {
            var sRet = "";
            try
            {
                if (qu == null || qu.IsEmpty)
                {
                    return sRet;
                }
                var iTimeOutCnt = 5;
                var i = 0;
                while (true)
                {
                    var b = qu.TryPeek(out var str);
                    if (b)
                    {
                        return str;
                    }
                    i++;
                    if (i >= iTimeOutCnt)
                    {
                        return sRet;
                    }
                    System.Threading.Thread.Sleep(2);
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNTryPeek Err:{ex.Message}");
            }
            return sRet;
        }

        public static string DNTryDequeue(this ConcurrentQueue<string> qu)
        {
            var sRet = "";
            try
            {
                if (qu == null || qu.IsEmpty)
                {
                    return sRet;
                }
                var iTimeOutCnt = 5;
                var i = 0;
                while (true)
                {
                    var b = qu.TryDequeue(out var str);
                    if (b)
                    {
                        return str;
                    }
                    i++;
                    if (i >= iTimeOutCnt)
                    {
                        return sRet;
                    }
                    System.Threading.Thread.Sleep(2);
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNTryDequeue Err:{ex.Message}");
            }
            return sRet;
        }

        public static T DNTryGetValue<K, T>(this ConcurrentDictionary<K, T> dic, K k)
        {
            try
            {
                if (!dic.ContainsKey(k))
                {
                    return default(T);
                }
                var i = 0;
                var iTimeOutCnt = 5;
                while (true)
                {
                    var b = dic.TryGetValue(k, out var t);
                    if (b)
                    {
                        return t;
                    }
                    i++;
                    if (i >= iTimeOutCnt)
                    {
                        return default(T);
                    }
                    System.Threading.Thread.Sleep(2);
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNTryGetValue Err:{ex.Message}");
            }
            return default(T);
        }


        public static T DNTryPeek2<T>(this ConcurrentQueue<T> qu)
        {
            //var sRet = "";
            try
            {
                if (qu == null || qu.IsEmpty)
                {
                    return default(T);//sRet;
                }
                var iTimeOutCnt = 5;
                var i = 0;
                while (true)
                {
                    var b = qu.TryPeek(out var str);
                    if (b)
                    {
                        return str;
                    }
                    i++;
                    if (i >= iTimeOutCnt)
                    {
                        return default(T);//sRet;
                    }
                    System.Threading.Thread.Sleep(2);
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNTryPeek2 Err:{ex.Message}");
            }
            return default(T);//sRet;
        }

        public static T DNTryDequeue2<T>(this ConcurrentQueue<T> qu)
        {
            //var sRet = "";
            try
            {
                if (qu == null || qu.IsEmpty)
                {
                    return default(T);//sRet;
                }
                var iTimeOutCnt = 5;
                var i = 0;
                while (true)
                {
                    var b = qu.TryDequeue(out var str);
                    if (b)
                    {
                        return str;
                    }
                    i++;
                    if (i >= iTimeOutCnt)
                    {
                        return default(T);//sRet;
                    }
                    System.Threading.Thread.Sleep(2);
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNTryDequeue2 Err:{ex.Message}");
            }
            return default(T);//sRet;
        }

        /// <summary>
        /// 对List列表对像进行分页
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="lt"></param>
        /// <param name="iPageSize"></param>
        /// <returns></returns>
        public static List<T[]> DNPaging<T>(this List<T> lt, int iPageSize = 10)
        {
            var ltRet = new List<T[]>();
            try
            {
                // 定义每页显示的数量
                int pageSize = iPageSize;
                // 获取要分页的字符串列表
                var stringList = lt;//GetStringList(); // 这里需要根据自己的业务逻辑获取到对应的字符串列表
                                    // 计算总共有多少页
                int totalPages = (int)Math.Ceiling((double)stringList.Count / pageSize);
                // 指定当前页码（从第一页开始）
                int currentPage = 1;
                while (true)
                {
                    // 判断输入的页码是否合法
                    if (currentPage < 1 || currentPage > totalPages)
                    {
                        //Console.WriteLine("无效的页码！");
                        break;
                    }
                    else
                    {
                        try
                        {
                            int startIndex = (currentPage - 1) * pageSize;
                            int endIndex = Math.Min(startIndex + pageSize, stringList.Count);

                            // 提取当前页的字符串列表
                            var currentPageStrings = stringList.GetRange(startIndex, endIndex - startIndex);

                            //// 打印当前页的内容
                            //foreach (var str in currentPageStrings)
                            //{
                            //    Console.WriteLine(str);
                            //}
                            var currPageStrings = currentPageStrings.ToArray();
                            ltRet.Add(currPageStrings);
                        }
                        catch (Exception ex)
                        {
                            LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNPaging 0Err:{ex.Message}");
                        }
                    }
                    currentPage++;
                }
            }
            catch (Exception ex)
            {
                LogWrite.TxtExport_DateNow("LogErr.txt", $"ToolHelper DNPaging Err:{ex.Message}");
            }
            return ltRet;
        }
    }

}
